/* @(#)FmsLibraryActivity.java
** 
** Copyright (C) 2012 by Steven D. Stamps
**
**             Trademarks & Copyrights
** Flywheel Management Science(TM), Flywheel Management Model(TM),
** Flywheel Story Editor(TM) and FlywheelMS(TM) are exclusive trademarks
** of Steven D. Stamps and may only be used freely for the purpose of
** identifying the unforked version of this software.  Subsequent forks
** may not use these trademarks.  All other rights are reserved.
**
** DecKanGL (Decorated Kanban Glyph Language) and TribKn (Tribal Knowledge)
** are also exclusive trademarks of Steven D. Stamps.  These may be used
** freely within the unforked FlywheelMS application and documentation.
** All other rights are reserved.
**
** gConGUI (game Controller Graphical User Interface) is an exclusive
** trademark of Steven D. Stamps.  This trademark may be used freely
** within the unforked FlywheelMS application and documentation.
** All other rights are reserved.
**
** Trademark information is available at
** <http://www.flywheelms.com/trademarks>
**
** Flywheel Management Science(TM) is a copyrighted body of management
** metaphors, governance processes, and leadership techniques that is
** owned by Steven D. Stamps.  These copyrighted materials may be freely
** used, without alteration, by the community (users and developers)
** surrounding this GPL3-licensed software.  Additional copyright
** information is available at <http://www.flywheelms.org/copyrights>
**
**              GPL3 Software License
** This program is free software: you can use it, redistribute it and/or
** modify it under the terms of the GNU General Public License, version 3,
** as published by the Free Software Foundation. This program is distributed
** in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
** even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
** PURPOSE.  See the GNU General Public License for more details. You should
** have received a copy of the GNU General Public License, in a file named
** COPYING, along with this program.  If you cannot find your copy, see
** <http://www.gnu.org/licenses/gpl-3.0.html>.
*/

package com.flywheelms.library;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.inputmethod.InputMethodManager;

import com.flywheelms.library.fdk.enumerator.FdkState;
import com.flywheelms.library.fdk.interfaces.FdkClient;
import com.flywheelms.library.fms.miscellaneous.FmsContext;
import com.flywheelms.library.gcg.helper.GcgHelper;

public abstract class FmsLibraryActivity extends Activity {
	
	private FdkState fdkState = FdkState.DISABLED;
	private MenuItem fdkMenuItem;
	private String helpContextUrlString = "";
	private boolean speechRecognitionSupported;
	private SpeechRecognizer speechRecognizer;
	private Intent speechRecognizerIntent;
	private DictationListener dictationListener = new DictationListener();
	private FdkClient fdkListener;
	private InputMethodManager inputManager;
	private int globalLayoutCounter = 0;
	private FmsContext fmsContext;
	
	public FmsLibraryActivity() {
		super();
	}
	
	public FmsLibraryActivity(String anInitialHelpContextUrlString) {
		this();
		this.helpContextUrlString = anInitialHelpContextUrlString;
	}
	
	public FmsContext getFmsContext() {
		return this.fmsContext;
	}

	public void setFmsContext(FmsContext fmsContext) {
		this.fmsContext = fmsContext;
	}

	@Override
	protected void onCreate(Bundle aSavedInstanceState) {
		super.onCreate(aSavedInstanceState);
		setContentView(getContentViewResourceId());
		this.inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 
		initSpeechRecognition();
		initSoftKeyboardManagement();
	}
	
	protected abstract int getContentViewResourceId();
	
	protected abstract int getActivityRootViewResourceId();
	
	private void initSoftKeyboardManagement() {
		final View activityRootView = findViewById(getActivityRootViewResourceId());
		activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
		    @Override
		    public void onGlobalLayout() {
		    	++FmsLibraryActivity.this.globalLayoutCounter;
		    	if(FmsLibraryActivity.this.globalLayoutCounter < 2 || FmsLibraryActivity.this.fdkState != FdkState.ACTIVE) {
		    		return;
		    	}
		        int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
		        if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
		        	FmsLibraryActivity.this.inputManager.hideSoftInputFromWindow(FmsLibraryActivity.this.getCurrentFocus().getWindowToken(),      
		        		    InputMethodManager.HIDE_NOT_ALWAYS);
		        }
		     }
		});
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		this.speechRecognizer.destroy();
	}
	
	@Override
	  public boolean onCreateOptionsMenu(Menu aMenu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.default_library_application_menu, aMenu);
	    this.fdkMenuItem = aMenu.findItem(R.id.action__flywheel_dictation_keyboard);
		this.fdkMenuItem.setIcon(this.fdkState.getDrawable());
	    return true;
	  } 
	
	@Override
	  public boolean onOptionsItemSelected(MenuItem aMenuItem) {
	    if(aMenuItem.getItemId() == R.id.action__help) {
	      Intent theIntent = new Intent(Intent.ACTION_VIEW, 
	    	       Uri.parse(getHelpContextUrlString()));
	    	startActivity(theIntent);
	    } else if(aMenuItem.getItemId() == R.id.action__flywheel_dictation_keyboard) {
	    	switch(this.fdkState) {
	    	case AVAILABLE:
	    		this.fdkState = FdkState.ACTIVE;
	    		this.fdkMenuItem.setIcon(this.fdkState.getDrawable());
	    		notifyFdkListener();
//	    		GcgHelper.makeToast("Flywheel Dictation Keyboard - Active");
	    		break;
	    	case ACTIVE:
	    		this.fdkState = FdkState.AVAILABLE;
	    		this.fdkMenuItem.setIcon(this.fdkState.getDrawable());
	    		notifyFdkListener();
//	    		GcgHelper.makeToast("Flywheel Dictation Keyboard - Available");
	    		break;
	    	case DISABLED:
	    		break;
    		default:
	    	}
	    }
	    return true;
	  } 
	
	public void initSpeechRecognition() {
		this.speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
		this.speechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
		this.speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
				RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
		this.speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
				this.getPackageName());
		this.speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 20);
		this.speechRecognizer.setRecognitionListener(this.dictationListener);
	}
	
	private void notifyFdkListener() {
			this.fdkListener.fdkNotifyStateChangeByActivity(this.fdkState);
	}
	
	public void registerFdkListener(FdkClient anFdkClient) {
		this.fdkListener = anFdkClient;
	}
	
	public void setHelpContextUrlString(String aHelpContextUrlString) {
		this.helpContextUrlString = aHelpContextUrlString;
	}

	public String getHelpContextUrlString() {
		return this.helpContextUrlString;
	}
	
	///////////////////
	
	public boolean speechRecognitionSupported() {
		return this.speechRecognitionSupported;
	}
	
	public void setFlywheelDictationKeyboardState(FdkState anFdkState) {
		if(this.fdkState == anFdkState) {
			return;
		}
		this.fdkState = anFdkState;
		if(this.fdkMenuItem != null) {  // action bar not yet instantiated
			this.fdkMenuItem.setIcon(anFdkState.getDrawable());
		}
	}
	
	public FdkState getFlywheelDictationKeyboardState() {
		return this.fdkState;
	}
	
//	@Override
//	public void onConfigurationChanged(Configuration newConfig) {
//	    super.onConfigurationChanged(newConfig);
//
//
//	    if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
//	        Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
//	    }
//	}
	
	public void startDictation() {
		this.speechRecognizer.startListening(this.speechRecognizerIntent);
//	    GcgHelper.makeToast("Start dictation...");
	}
	
//    @Override
//    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//    	//check speech recognition result 
//    	if (requestCode == VR_REQUEST && resultCode == RESULT_OK) {
//    		//store the returned word list as an ArrayList
//    		ArrayList<String> theWordList = data.
//    				getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
//    		this.fdkListener.dictationResults(theWordList);
//    	}
//    }

	public void stopDictation() {
		this.speechRecognizer.stopListening();
//		GcgHelper.makeToast("Stop dictation...");
	}

	public void cancelDictation() {
		this.speechRecognizer.cancel();
		GcgHelper.makeToast("Cancel dictation...");
	}
	
	protected class DictationListener implements RecognitionListener {

	    @Override
	    public void onBeginningOfSpeech() {      
	    	return;
	    }

	    @Override
	    public void onBufferReceived(byte[] buffer) {     
	    	return;
	    }

	    @Override
	    public void onEndOfSpeech() {  
	    	return;
	    }

	    @Override
	    public void onError(int error) {
//	         speechRecognizer.startListening(speechRecognizerIntent);
	    	return;
	    }

	    @Override
	    public void onEvent(int eventType, Bundle params) {      
	    	return;
	    }

	    @Override
	    public void onPartialResults(Bundle partialResults) {      
	    	return;
	    }

	    @Override
	    public void onReadyForSpeech(Bundle params) {      
	    	return;
	    }

	    @Override
	    public void onResults(Bundle theDictationResults) {      
	        ArrayList<String> theWordList = theDictationResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
	        FmsLibraryActivity.this.fdkListener.fdkDictationResults(theWordList);
	    }

	    @Override
	    public void onRmsChanged(float rmsdB) {      
	    	return;
	    }

	}

}
